<?php
/**
 * spRun  执行用户代码
 */
function Run(){
	GLOBAL $__module, $__controller, $__action;
	
	//forthxu,对控制器路径包装
	$GLOBALS['config']['controller_path'] = APPS.'/'.$__module.'/'.$GLOBALS['config']["controller_directory"];
	//forthxu,对模型路径包装
	$GLOBALS['config']['model_path'] = APPS.'/'.$__module.'/'.$GLOBALS['config']["model_directory"];
	//forthxu,对库路径包装
	$GLOBALS['config']['lib_path'] = APPS.'/'.$__module.'/'.$GLOBALS['config']["lib_directory"];
	//forthxu,对模板路径包装
	$GLOBALS['config']['view_path']= TPL.'/'.$__module;

	//forthxu,模块函数
	file_exists($GLOBALS['config']['lib_path'].'/function.'.$__module.'.php') ? require($GLOBALS['config']['lib_path'].'/function.'.$__module.'.php'):'';
	//forthxu,模块基础类
	file_exists($GLOBALS['config']['lib_path'].'/class.'.$__module.'.php') ? require($GLOBALS['config']['lib_path'].'/class.'.$__module.'.php'):'';
	
	$handle_controller = spClass($__controller, null, $GLOBALS['config']['controller_path'].'/'.$__controller.".php");
	
	// 调用控制器出错将调用路由错误处理函数
	if(!is_object($handle_controller) || (!method_exists($handle_controller, $__action) && !method_exists($handle_controller, '__call'))){
		echo "无可执行";exit;
		exit;
	}
	
	// 路由并执行用户代码
	$handle_controller->$__action();
	
}

/**
 * ConfigReady   快速将用户配置覆盖到框架默认配置
 * 
 * @param preconfig    默认配置
 * @param useconfig    用户配置
 */
function ConfigReady( $preconfig, $useconfig = null){
	$nowconfig = $preconfig;
	if (is_array($useconfig)){
		foreach ($useconfig as $key => $val){
			if (is_array($useconfig[$key])){
				@$nowconfig[$key] = is_array($nowconfig[$key]) ? ConfigReady($nowconfig[$key], $useconfig[$key]) : $useconfig[$key];
			}else{
				@$nowconfig[$key] = $val;
			}
		}
	}
	return $nowconfig;
}

/**
 * import  载入包含文件
 * 
 * @param filename    需要载入的文件名或者文件路径
 * @param auto_search    载入文件找不到时是否搜索系统路径或文件，搜索路径的顺序为：应用程序包含目录 -> 应用程序Model目录 -> sp框架包含文件目录
 * @param auto_error    自动提示扩展类载入出错信息
 */
function import($sfilename, $auto_search = TRUE, $auto_error = FALSE){
	if(isset($GLOBALS['config']["import_file"][md5($sfilename)]))return TRUE; // 已包含载入，返回
	// 检查$sfilename是否直接可读
	if( TRUE == @is_readable($sfilename) ){
		require($sfilename); // 载入文件
		$GLOBALS['config']['import_file'][md5($sfilename)] = TRUE; // 对该文件进行标识为已载入
		return TRUE;
	}else{
		if(TRUE == $auto_search){ // 需要搜索文件
			// forthxu,按“应用程序Model目录 ->统一系统程序包含目录 ->  sp框架包含文件目录”的顺序搜索文件
			foreach(array($GLOBALS['config']['include_path'],$GLOBALS['config']['misc_path']) as $sp_include_path){
				// 检查当前搜索路径中，该文件是否已经载入
				if(isset($GLOBALS['config']["import_file"][md5($sp_include_path.'/'.$sfilename)]))return TRUE;
				if( @is_readable( $sp_include_path.'/'.$sfilename ) ){
					require($sp_include_path.'/'.$sfilename);// 载入文件
					$GLOBALS['config']['import_file'][md5($sp_include_path.'/'.$sfilename)] = TRUE;// 对该文件进行标识为已载入
					return TRUE;
				}
			}
		}
	}
	if( TRUE == $auto_error )spError("未能找到名为：{$sfilename}的文件");
	return FALSE;
}

/**
 * spClass  类实例化函数  自动载入类定义文件，实例化并返回对象句柄
 * 
 * @param class_name    类名称
 * @param args   类初始化时使用的参数，数组形式
 * @param sdir 载入类定义文件的路径，可以是目录+文件名的方式，也可以单独是目录。sdir的值将传入import()进行载入
 * @param force_inst 是否强制重新实例化对象
 */
function spClass($class_name, $args = null, $sdir = null, $force_inst = FALSE){
	// 检查类名称是否正确，以保证类定义文件载入的安全性
	if(preg_match('/[^a-z0-9\-_.]/i', $class_name))spError($class_name."类名称错误，请检查。");
	// 检查是否该类已经实例化，直接返回已实例对象，避免再次实例化
	if(TRUE != $force_inst)if(isset($GLOBALS['config']["inst_class"][$class_name]))return $GLOBALS['config']["inst_class"][$class_name];
	// 如果$sdir不能读取，则测试是否仅路径
	//forthxu,先查目录文件,目录参数不为空时，引入目录下指定文件为空并且目录参数当做文件引入也为空，返回失败
	if(null != $sdir && !import($sdir.'/'.$class_name.'.php') && !import($sdir))return FALSE;
	
	$has_define = FALSE;
	// 检查类定义是否存在
	if(class_exists($class_name, false) || interface_exists($class_name, false)){
		$has_define = TRUE;
	}else{
		if( TRUE == import($class_name.'.php')){
			$has_define = TRUE;
		}
	}
	if(FALSE != $has_define){
		$argString = '';$comma = ''; 
		if(null != $args)for ($i = 0; $i < count($args); $i ++) { $argString .= $comma . "\$args[$i]"; $comma = ', '; } 
		eval("\$GLOBALS['config']['inst_class'][\$class_name]= new \$class_name($argString);"); 
		return $GLOBALS['config']["inst_class"][$class_name];
	}
	spError($class_name."类定义不存在，请检查。");
}

/**
 * spError 框架定义的系统级错误提示
 * 
 * @param msg    出错信息
 * @param output    是否输出
 * @param stop    是否停止程序
 */
function spError($msg, $output = TRUE, $stop = TRUE){
	if($GLOBALS['config']['sp_error_throw_exception'])throw new Exception($msg);
	if(TRUE != SP_DEBUG){error_log($msg);if(TRUE == $stop)exit;}
	$traces = debug_backtrace();
	$bufferabove = ob_get_clean();
	require_once($GLOBALS['config']['sp_notice_php']);
	if(TRUE == $stop)exit;
}
?>